﻿using SharpDX;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;

namespace Ensemble_Windows
{
    /// <summary>
    /// Direct3D11 Render
    /// </summary>
    public class Direct3D11Render : Direct
    {
        SharpDX.Direct3D11.Device _device;
        SwapChain _swapChain;
        Texture2D _backBuffer { get; set; }
        RenderTargetView _backBufferView { get; set; }

        /// <summary>
        /// 返回Device
        /// </summary>
        public SharpDX.Direct3D11.Device Device
        {
            get { return _device; }
        }

        /// <summary>
        /// 返回backbuffer使用于SwapChain
        /// </summary>
        public Texture2D BackBuffer
        {
            get { return _backBuffer; }
        }

        /// <summary>
        /// 返回渲染目标视图使用于SwapChain
        /// </summary>
        public RenderTargetView BackBufferView
        {
            get { return _backBufferView; }
        }

        /// <summary>
        /// 游戏初始化
        /// </summary>
        /// <param name="configuration">配置</param>
        protected override void Initialize(Configuration configuration)
        {
            var desc = new SwapChainDescription()
            {
                BufferCount = 1,
                ModeDescription = new ModeDescription(configuration.Width, configuration.Height,
                    new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed = true,
                OutputHandle = DisplayHandle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect = SwapEffect.Discard,
                Usage = Usage.RenderTargetOutput
            };

            SharpDX.Direct3D11.Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport,
                new[] { FeatureLevel.Level_10_0 }, desc, out _device, out _swapChain);

            Factory factory = _swapChain.GetParent<Factory>();
            factory.MakeWindowAssociation(DisplayHandle, WindowAssociationFlags.IgnoreAll);

            _backBuffer = Texture2D.FromSwapChain<Texture2D>(_swapChain, 0);

            _backBufferView = new RenderTargetView(_device, _backBuffer);
        }

        /// <summary>
        /// 开始绘图
        /// </summary>
        protected override void BeginDraw()
        {
            base.BeginDraw();
            Device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, Config.Width, Config.Height));
            Device.ImmediateContext.OutputMerger.SetTargets(_backBufferView);
        }

        /// <summary>
        /// 结束绘图
        /// </summary>
        protected override void EndDraw()
        {
            _swapChain.Present(Config.WaitVerticalBlanking ? 1 : 0, PresentFlags.None);
        }
    }
}
